package com.chenyanqing.model.two.factory;

import com.chenyanqing.model.two.annotation.AnnotationTypeConfig;
import com.chenyanqing.model.two.annotation.TimeLog;
import com.chenyanqing.model.two.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class AnnotationAspectJAutoProxyCreator<T> {


    private AnnotationAspectJAutoProxyCreator(){

    }

    private static AnnotationAspectJAutoProxyCreator proxyCreator= new AnnotationAspectJAutoProxyCreator();

    public  static AnnotationAspectJAutoProxyCreator getInstance(){
        return proxyCreator;
    }


    /**
     * 根据注解配置，创建代理对象
     * @return
     */
    public  T   processAnnotationAspectProxy(T t){
        if(t==null){
            return t;
        }

        //遍历需要处理的注解，层层处理对应的代理逻辑
        List<AnnotationTypeConfig> annotationTypeConfigs = extractAnnotationConfig(t.getClass());
        if(!CollectionUtils.isEmpty(annotationTypeConfigs)) {
            for (AnnotationTypeConfig annotationTypeConfig : annotationTypeConfigs) {
                t = (T)annotationTypeConfig.getProxyFactory().getJDKProxy(t);
            }
            return t;
        }else {
            return t;
        }

    }





    private List<AnnotationTypeConfig> extractAnnotationConfig(Class<?> aClass){
        List<AnnotationTypeConfig> configs = new ArrayList<>();
        if(isTransactional(aClass)){
            configs.add(AnnotationTypeConfig.TRANSACTION);
        }

        if(isTimeLogAnnotation(aClass)){
            configs.add(AnnotationTypeConfig.TIMELOG);
        }
        return configs;
    }


    /**
     * 判断是否是事务注解
     * @param aClass
     * @return
     */
    private boolean isTransactional(Class<?> aClass){
        Transactional classTransactionAnnotation = aClass.getAnnotation(Transactional.class);
        if(classTransactionAnnotation!=null){
            return true;
        }else{
            Method[] declaredMethods = aClass.getDeclaredMethods();
            if(declaredMethods!=null){
                for (Method declaredMethod : declaredMethods) {
                    if(declaredMethod.getAnnotation(Transactional.class)!=null){
                        return true;
                    }
                }
            }

        }
        return false;
    }


    /**
     * 是否是TimeLog注解
     * @param aClass
     * @return
     */
    private boolean isTimeLogAnnotation(Class<?> aClass){
        Method[] declaredMethods = aClass.getDeclaredMethods();
        if(declaredMethods!=null){
            for (Method declaredMethod : declaredMethods) {
                if(declaredMethod.getAnnotation(TimeLog.class)!=null){
                    return true;
                }
            }
        }
        return false;

    }

}
